﻿using System;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.U2D;
using UnityEngine.UI;

namespace HEFramework
{
    public static class TeamUISystem
    {
        [EntitySystem]
        public class TeamUIAwakeSystem : AwakeSystem<TeamUI>
        {
            protected override void Awake(TeamUI _self)
            {
                _self.AddChild<UnityObjectComponent>();
            }
        }

        [EntitySystem]
        public class TeamUIUpdateSystem : UpdateSystem<TeamUI>
        {
            protected override void Update(TeamUI _self)
            {
                _self.Update();
            }
        }

        [EntitySystem]
        public class TeamUIDestroySystem : DestroySystem<TeamUI>
        {
            protected override void Destroy(TeamUI _self)
            {
                _self.Close();
            }
        }


        public static void Open(this TeamUI _self)
        {
            var uc = _self.GetSceneChild<UIComponent>();
            if (uc == null)
            {
                return;
            }

            uc.PushUIAsync(eUIFlag.Team, _ =>
            {
                _self.UIWindowBehaviour = _;
                _self.Bind();
                _self.SelectID = -1;
                _self.Update(true);
            });
        }

        public static void Bind(this TeamUI _self)
        {
            if (_self.UIWindowBehaviour == null)
            {
                return;
            }

            var dc = _self.GetSceneChild<DataTableComponent>();
            if (dc == null)
            {
                return;
            }

            _self.UIWindowBehaviour.GetButton("Button_Back").RegisterUpEvent(_self.Close);
            int max = dc.LoadDataTable<DRGlobalSettings>().GetData((int)eGlobalSetting.TeamPeople_MaxNum).Value1;
            for (int i = 0; i < max; i++)
            {
                int index = i;
                _self.UIWindowBehaviour.GetButton($"Button_TeamItem{i}").RegisterUpEvent(() => { _self.Select(index); });
            }
        }

        public static void Update(this TeamUI _self, bool _isNew = false)
        {
            if (_self.UIWindowBehaviour == null || _self.UIWindowBehaviour.State == 0)
            {
                return;
            }

            var dc = _self.GetSceneChild<DataTableComponent>();
            var team = _self.GetSceneChild<Team>();

            if (dc == null || team == null)
            {
                return;
            }

            _self.UpdateTeamButton(_isNew);
        }

        public static void Close(this TeamUI _self)
        {
            if (_self.UIWindowBehaviour == null)
            {
                return;
            }

            _self.RecyclePrefab();
            _self.UIWindowBehaviour.Hide();
            _self.UIWindowBehaviour = null;
        }

        public static void Select(this TeamUI _self, int _index)
        {
            var team = _self.GetSceneChild<Team>();
            if (team == null)
            {
                return;
            }

            _self.SelectID = (team.GetHeroByIndex(_index) as Hero).ID;
            var heroInfoUI = _self.GetSceneChild<HeroInfoUI>();
            heroInfoUI?.Open();
        }

        private static void UpdateTeamButton(this TeamUI _self, bool _isNew)
        {
            if (_self.UIWindowBehaviour == null)
            {
                return;
            }

            var team = _self.GetSceneChild<Team>();
            var pc = _self.GetSceneChild<PrefabComponent>();
            var dc = _self.GetSceneChild<DataTableComponent>();
            var rc = _self.GetSceneChild<ResourcesComponent>();
            var uc = _self.GetChild<UnityObjectComponent>();
            if (team == null || pc == null || dc == null || rc == null || uc == null)
            {
                return;
            }

            var hero_table = dc.LoadDataTable<DRHero>();
            var attribute_table = dc.LoadDataTable<DRAttribute>();
            var language_table = dc.LoadDataTable<DRLanguage>();
            var skill_table = dc.LoadDataTable<DRSkill>();
            int max = dc.LoadDataTable<DRGlobalSettings>().GetData((int)eGlobalSetting.TeamPeople_MaxNum).Value1;

            if (_isNew)
            {
                _self.RecyclePrefab();
            }


            string empty = " ";
            string backslash = "/";
            string second = "s";
            string add = "+";
            string cut = "-";
            string pct = "%";

            for (int i = 0; i < max; i++)
            {
                var button = _self.UIWindowBehaviour.GetButton($"Button_TeamItem{i}");
                Transform transform = button.GetTransform();
                var icon = transform.GetChild(0);
                var state = transform.GetChild(1);
                //-----
                var name = state.GetChild(0);
                var rank = state.GetChild(1);
                var attribute = state.GetChild(2);
                var skill = state.GetChild(3);
                var lv = state.GetChild(4);

                //0图标 1状态
                if (i < team.Heros.Count)
                {
                    button.Enable(true);
                    icon.gameObject.SetActive(true);
                    state.gameObject.SetActive(true);

                    var hero = team.Heros[i].Entity as Hero;
                    var hero_ac = hero.GetChild<AttributeComponent>();
                    var hero_sc = hero.GetChild<SkillComponent>();
                    var hData = hero_table.GetData(hero.ID);
                    var aData = attribute_table.GetData(hData.ID);

                    #region 角色

                    if (_isNew)
                    {
                        uc.Get<TMP_Text>(name.gameObject).text = aData.Name;

                        string extend = "_Image";
                        string abName = Formula.CN(aData.ABName, 0) + extend;
                        //异步加载
                        pc.GetPrefabAsync(aData.ABPath, abName, _ =>
                        {
                            //加载完成时发现UI关闭，则回收
                            if (_self.UIWindowBehaviour != null && _self.UIWindowBehaviour.State != 1)
                            {
                                pc.Recycle(aData.ABPath, abName, _);
                            }
                            else
                            {
                                _.transform.SetParent(icon, false);
                                _.transform.localPosition = Vector2.zero;
                                var image = new TeamUI.Image();
                                image.ID = aData.ID;
                                image.ABPath = aData.ABPath;
                                image.ABName = aData.ABName;
                                image.Obj = _;
                                _self.HeroImages.Add(image);
                            }
                        });
                    }

                    #endregion

                    #region 等级

                    var lv_filled = lv.GetChild(1);
                    var lv_text = lv.GetChild(2);
                    uc.Get<Image>(lv_filled.gameObject).fillAmount = (float)hero_ac.LV_EXP_PCT();
                    uc.Get<TMP_Text>(lv_text.gameObject).text = hero_ac.LV.ToString();

                    #endregion

                    #region 星级

                    for (int j = 0; j < rank.childCount; j++)
                    {
                        var rank_item = rank.GetChild(j);
                        if (j < hero_ac.RANK)
                        {
                            rank_item.gameObject.SetActive(true);
                        }
                        else
                        {
                            rank_item.gameObject.SetActive(false);
                        }
                    }

                    #endregion

                    #region 属性

                    var attribute_text = attribute.GetChild(1);
                    var sb = _self.StringBuilder;
                    sb.Clear();

                    //生命
                    sb.Append(language_table.GetData(100).Text);
                    sb.Append(empty);
                    sb.Append(empty);
                    sb.Append((int)hero_ac.HP);
                    sb.Append(backslash);
                    sb.Append((int)hero_ac.X_HP.Value);
                    sb.AppendLine();
                    //魔法
                    sb.Append(language_table.GetData(101).Text);
                    sb.Append(empty);
                    sb.Append(empty);
                    sb.Append((int)hero_ac.MP);
                    sb.Append(backslash);
                    sb.Append((int)hero_ac.X_MP.Value);
                    sb.AppendLine();
                    //攻击
                    sb.Append(language_table.GetData(102).Text);
                    sb.Append(empty);
                    sb.Append(empty);
                    sb.Append((int)hero_ac.P_ATK.Value);
                    sb.AppendLine();
                    //法术
                    sb.Append(language_table.GetData(115).Text);
                    sb.Append(empty);
                    sb.Append(empty);
                    sb.Append((int)hero_ac.M_ATK.Value);
                    sb.AppendLine();
                    //防御
                    sb.Append(language_table.GetData(103).Text);
                    sb.Append(empty);
                    sb.Append(empty);
                    sb.Append((int)hero_ac.P_DEF.Value);
                    sb.AppendLine();

                    uc.Get<TMP_Text>(attribute_text.gameObject).text = sb.ToString();

                    #endregion

                    #region 技能

                    int skill_count = skill.childCount;
                    for (int j = 0; j < skill_count; j++)
                    {
                        int index = j;
                        var skill_item = skill.GetChild(index);
                        var skill_icon = skill_item.GetChild(0);
                        var skill_mask = skill_item.GetChild(1);
                        if (j < hero_sc.SkillIDs.Count)
                        {
                            skill_icon.gameObject.SetActive(true);
                            skill_mask.gameObject.SetActive(true);
                            int skill_id = hero_sc.SkillIDs[index];
                            var skill_data = skill_table.GetData(skill_id);
                            if (_isNew)
                            {
                                rc.Assets.LoadAssetAsync<UnityEngine.Object>(skill_data.ABPath, skill_data.ABName, ResourceConfig.Extension.TEXTURE, _ =>
                                {
                                    Sprite sprite = null;
                                    if (_ is Texture2D t)
                                    {
                                        sprite = Sprite.Create(t, new Rect(0, 0, t.width, t.height), new Vector2(0.5f, 0.5f));
                                    }

                                    if (_ is Sprite s)
                                    {
                                        sprite = s;
                                    }

                                    uc.Get<Image>(skill_icon.gameObject).sprite = sprite;
                                });
                            }

                            var image = uc.Get<Image>(skill_mask.gameObject);

                            if (hero_sc.IsLock(skill_id))
                            {
                                image.fillAmount = 1;
                            }
                            else
                            {
                                switch (skill_data.Type)
                                {
                                    case (int)eSkillType.Active:
                                    case (int)eSkillType.Both:
                                        image.fillAmount = (float)hero_sc.Skill_CD_PCT(skill_id, true);
                                        break;
                                    case (int)eSkillType.Passive:
                                        image.fillAmount = (float)hero_sc.Skill_CD_PCT(skill_id, false);
                                        break;
                                }
                            }
                        }
                        else
                        {
                            skill_icon.gameObject.SetActive(false);
                            skill_mask.gameObject.SetActive(false);
                        }
                    }

                    #endregion
                }
                else
                {
                    button.Enable(false);
                    icon.gameObject.SetActive(false);
                    state.gameObject.SetActive(false);
                }
            }
        }

        private static void RecyclePrefab(this TeamUI _self)
        {
            var pc = _self.GetSceneChild<PrefabComponent>();

            if (pc == null)
            {
                return;
            }

            string extend = "_Image";
            //表示之前招募过,回收对象
            if (_self.HeroImages.Count > 0)
            {
                for (int i = 0; i < _self.HeroImages.Count; i++)
                {
                    var image = _self.HeroImages[i];
                    pc.Recycle(image.ABPath, Formula.CN(image.ABName, 0) + extend, image.Obj);
                }

                _self.HeroImages.Clear();
            }
        }
    }
}